//////////////////////////////////////////////////////////////////////////////////
//	 Copyright 2011 by Yosef Grabivker, ryuho@homenetworksoft.com
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//////////////////////////////////////////////////////////////////////////////////

#include <wx/wx.h>
#include "rtevents.h"
#include "guilogic.h"
#include "mainwnd.h"
#include "syslogsrv.h"
#include "../syslog/liblogging.h"
#include "../syslog/srAPI.h"
#include "../syslog/syslogmessage.h"

CSysLogSrv::CSysLogSrv(class CMainWnd& wMain, CGUILogic& clsGUILogic, int nPortUDP):
	wxThread(wxTHREAD_DETACHED), m_wMain(wMain), m_clsGUILogic(clsGUILogic), m_nPortUDP(nPortUDP)
{
}

CSysLogSrv::~CSysLogSrv(void)
{
	m_clsGUILogic.OnSysLogThreadFinished();
}

void CSysLogSrv::Start()
{
	m_bWorking = false;

	if ( wxTHREAD_NO_ERROR !=Create() ) THROW_EXC(cERFailed);

	SetPriority(WXTHREAD_MIN_PRIORITY);
		
	if ( wxTHREAD_NO_ERROR !=Run() ) THROW_EXC(cERFailed);
}

void CSysLogSrv::Stop()
{
	if ( m_pAPI ) srAPIShutdownListener(m_pAPI);

	wxThread::Delete();
}

//////////////////////////////////////////////////////////////////////////
//Thread
void CSysLogSrv::OnNewMessage()
{
	wxCommandEvent eventCustom(wxEVT_ON_SYSLOGMSG);
	eventCustom.SetId(0);
	wxPostEvent(&m_wMain, eventCustom);
}

void OnReceive(srAPIObj* pAPI, srSLMGObj* pSLMG)
{
	char *pszRemoteHost=NULL;
	char *pszHost=NULL;
	unsigned char *pszMSG=NULL;
	unsigned char *pszRawMsg=NULL;
	unsigned char *pszTag=NULL;
	int	iFacil;
	int iPrio;
	char* szNotWellformed = "";

	//--------------------------->
	#ifdef _WIN32
	OutputDebugString(wxT("On sys log message\n"));
	#endif
	//--------------------------->

	srSLMGGetRemoteHost(pSLMG, &pszRemoteHost);
	srSLMGGetPriority(pSLMG, &iPrio);
	srSLMGGetFacility(pSLMG, &iFacil);
	srSLMGGetRawMSG(pSLMG, &pszRawMsg);
	srSLMGGetTag(pSLMG,  &pszTag);

	if(srSLMGGetHostname(pSLMG, &pszHost) == SR_RET_PROPERTY_NOT_AVAILABLE)
		pszHost = szNotWellformed;

	srSLMGGetMSG(pSLMG, &pszMSG);

	CSysLogSrv* pSrv = (CSysLogSrv*)pAPI->pUsr;

	if ( pSrv )
	{
		try
		{
			SYSLOGMSG msg;
		
			msg.tm = time(NULL);

			if ( pSLMG->pszTimeStamp )
				msg.strTime = wxString::FromAscii((const char*)pSLMG->pszTimeStamp);

			if ( pszRemoteHost )
			{
				msg.strHost = wxString::FromAscii(pszHost);

				if ( msg.strHost.empty() )
				{
					msg.strHost = wxString::FromAscii(pszRemoteHost);
				}
			}

			msg.iFacil=iFacil;
			msg.iPrio=iPrio;

			if (pszMSG)
				msg.strMsg = wxString::FromAscii((const char*)pszMSG);

			if (pszTag)
				msg.strTag = wxString::FromAscii((const char*)pszTag);

			msg.strTag.Replace(wxT(":"),wxT("") );
			msg.strTime.Replace(wxT(">"),wxT("") );

			if (pSLMG->pszRawMsg)
				msg.strRaw = wxString::FromAscii( (const char*)pSLMG->pszRawMsg);


			COMMANDRESPONSE response;
			response.code = cCmdSysLogMessage;
			response.msg  = msg;

			pSrv->AddResponce( response );
			pSrv->OnNewMessage();
		}catch(...) {}
	}
}

void* CSysLogSrv::Entry()
{
	srRetVal	iRet;

	#ifdef WIN32
	__try{
	#endif

	if((m_pAPI = srAPIInitLib()) == NULL)
	{
		return NULL;
	}

	m_pAPI->pUsr = this;

	if((iRet = srAPISetOption(m_pAPI, srOPTION_UPD_LISTENPORT, m_nPortUDP)) != SR_RET_OK)
	{
		return NULL;
	}


/* We now set the options so that the server receives all we desire... */
	if((iRet = srAPISetOption(m_pAPI, srOPTION_LISTEN_UDP, TRUE)) != SR_RET_OK)
	{
		return NULL;
	}

	if((iRet = srAPISetOption(m_pAPI, srOPTION_LISTEN_UXDOMSOCK, TRUE)) != SR_RET_OK)
	{
		return NULL;
	}

	if((iRet = srAPISetupListener(m_pAPI, OnReceive)) != SR_RET_OK)
	{
		return NULL;
	}

	/* now move the listener to running state. Control will only
	 * return after SIG_INT.
	 */
	if((iRet = srAPIRunListener(m_pAPI)) != SR_RET_OK)
	{
		return NULL;
	}

	/** control will reach this point after SIG_INT */

	srAPIExitLib(m_pAPI);

	m_pAPI = NULL;

	#ifdef WIN32
	}__finally{ }
	#endif

	return NULL;
}
